package com.job.security.config;


import com.job.security.component.JwtAuthenticationTokenFilter;
import com.job.security.component.RestAuthenticationEntryPoint;
import com.job.security.component.RestfulAccessDeniedHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;

/**
 * @Description:
 * @Author: yqz
 * @CreateDate: 2020/10/25 16:30
 */

import org.springframework.security.authentication.AuthenticationProvider;

import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.http.HttpMethod;

@Configuration
@EnableWebSecurity
public class BaseSecurityConfig {

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;

    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors(cors -> cors.configurationSource(corsConfigurationSource())).csrf(csrf -> csrf.disable())
                .exceptionHandling(exception -> {
                    exception.authenticationEntryPoint(restAuthenticationEntryPoint);
                    exception.accessDeniedHandler(restfulAccessDeniedHandler);
                })
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(
                                "/login",
                                "wx/getOpenId",
                                "wx/bind"
                                // 小程序首页
                        )
                        .permitAll()
                        .requestMatchers(HttpMethod.OPTIONS) // 跨域请求会先进行一次options请求
                        .permitAll()
                        .anyRequest()
                        .authenticated())
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public AuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
//}
//public class BaseSecurityConfig extends WebSecurityConfigurerAdapter {
//    @Autowired
//    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
//    @Autowired
//    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
//    @Autowired
//    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
//
//    /**
//     * 允许基于选择匹配在资源级配置基于网络的安全性。
//     * 以下示例将以/ admin /开头的网址限制为具有ADMIN角色的用户，并声明任何其他网址需要成功验证。
//     * 也就是对角色的权限——所能访问的路径做出限制
//     */
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        //首页所有人可以访问，功能只有对应权限的人才可以访问
//        //请求授权的规则
//        http.authorizeRequests()
//                .antMatchers(
//                        "/admin/auth/login",
//                        //小程序首页
//                        "/client/home/*","/client/auth/*","/client/goods/count",
//                        "/doc.html",
//                        "/swagger-resources/**",
//                        "/swagger/**",
//                        "/**/v2/api-docs",
//                        "/**/*.js",
//                        "/**/*.css",
//                        "/**/*.png",
//                        "/**/*.ico",
//                        "/webjars/springfox-swagger-ui/**")
//                .permitAll()
//                .antMatchers(HttpMethod.OPTIONS) //跨域请求会先进行一次options请求
//                .permitAll()
//                // 除了以上路径，其他都需要验证
//                .anyRequest()
//                .authenticated();
//        // 禁用缓存
//        http.headers().cacheControl();
//        //防止网站攻击：get post
//        http.csrf().disable();//关闭csrf跨站攻击，登出失败可能的原因
//
//        //基于token所以不需要session
//        http.sessionManagement()
//                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//
//        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
//        http.exceptionHandling()
//                .accessDeniedHandler(restfulAccessDeniedHandler)
//                .authenticationEntryPoint(restAuthenticationEntryPoint);
//
//        http.authorizeRequests()
//                .and()
//                .formLogin()
//                .and()
//                .httpBasic();
//
//    }
//
//    /**
//     * 用于通过允许AuthenticationProvider容易地添加来建立认证机制。
//     * 也就是说用来记录账号，密码，角色信息。
//     */
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//
//        //此处把用户信息交给security校验
//        auth.userDetailsService(userDetailsService())
//                .passwordEncoder(passwordEncoder());
//    }
//
//    /**
//     * SpringSecurity5.0以后，密码需要加密
//     * @return
//     */
//    @Bean
//    public PasswordEncoder passwordEncoder() {
//        return new BCryptPasswordEncoder();
//    }
//
//
//    @Override
//    @Bean
//    public AuthenticationManager authenticationManager() throws Exception {
//        return super.authenticationManager();
//    }
//}
